import os
import sys
import random
import string

C__FILENAME = "ex2_autogen_tester.cpp"
C__NUM_FUNCTIONS = 50;
C__LIB_INCLUDES = ["iostream"];
C__USER_INCLUDES = ["uthreads.h","user_thread.h","common_defs.h"] ;

# CUSTOMIZE
C__ENABLE_SLEEP_IN_THREAD = False;
C__SLEEP_SECS = 1;
C__WAIT_FOR_THREADS = False;

def generate_includes(i__fileHandler):
    for inc in C__LIB_INCLUDES:
        s__inc = '#include <' + inc + '>\n' 
        i__fileHandler.write(s__inc);
    for inc in C__USER_INCLUDES:
        s__inc = '#include "' + inc + '"\n' 
        i__fileHandler.write(s__inc);
    
    i__fileHandler.write("using namespace std;\n#define SECOND 1000000\n");
    i__fileHandler.flush();


def generate_functions(i__fileHandler):
    function_names = []; 
    for i in range(1,C__NUM_FUNCTIONS):
        
        # Function declaration
        s__func_name = ''.join(random.choice(string.ascii_lowercase) for x in range(5))
        s__declaration = "void %s (void)\n{" % (s__func_name)
        i__fileHandler.write(s__declaration);
                
        # Annotate function
        s__anotate = "\n \t \n";
        s__anotate = '\n\tDBG_PRINT("Starting function %d\\n",0);'
        i__fileHandler.write(s__anotate);
        
           
        # GET ID Thread
        s__get = "\n\tint id;"
        s__get += "\n\tid = thread_gettid();"
        i__fileHandler.write(s__get)
        

        
        # Suspend Some Thread (Randomly)
        s__suspend = "\n\t"
        s__suspend += "thread_suspend (%s);" % (random.randrange(0,C__NUM_FUNCTIONS));
        if(random.randrange(0,2)):
            i__fileHandler.write(s__suspend)
            
        # Sleep INSIDE thread (Randomly)
        if(C__ENABLE_SLEEP_IN_THREAD):
            s__sleep_t = "\n\t"
            s__sleep_t += "usleep(" + C__SLEEP_SECS + "*SECOND);"
            if(random.randrange(0,2)):
                i__fileHandler.write(s__sleep_t)
            
            
        # Annotate End of function
        s__anotate = "\n\t\n";
        s__anotate = '\n\tDBG_PRINT("End of function %d\\n",0);\n'
        i__fileHandler.write(s__anotate);
        
        # End of functions
        s__declaration = "\tthread_terminate(id);\n}\n"
        i__fileHandler.write(s__declaration);
        function_names.append(s__func_name);
    return function_names;


def generate_test(i__fileHandler,functions):
    
    # Create Main
    s__main = "int main()\n{\n";
    i__fileHandler.write(s__main);
    
    # Init local vars
    s__local_vars = "\tint res;\n"
    i__fileHandler.write(s__local_vars);
    
    # Init library
    s__init_library = "\tres = thread_lib_init();\n"
    s__init_library += '\tif ( res )\n\t{\n\t\tcerr << "thread_lib_init failed" << endl;\n\t\treturn res;\n\t}\n';
    i__fileHandler.write(s__init_library);
    
    # Spawn functions
    for func_name in functions:
        s__spawn_func = "\t"
        s__spawn_func += "res = thread_spawn( %s , %s);" %(func_name,str(random.randrange(0,32)))
        s__spawn_func += "\n\t"
        s__spawn_func += "if ( -1 == res )"
        s__spawn_func += "\n\t{\n\t\t"
        s__spawn_func +=  'cerr <<  __LINE__ << ": thread_spawn() for function %s failed" << endl;' %(func_name);
        s__spawn_func += "\n\t}\n"
        i__fileHandler.write(s__spawn_func);
    
    # Allow closure of other sleeping threads
    if(C__WAIT_FOR_THREADS):
        s__main_sleep = "\n\tusleep(10*SECOND);";
        i__fileHandler.write(s__main_sleep);
    
    # Close Main 
    s__anotate = '\n\tDBG_PRINT("End of Main.\\n");\n\tthread_terminate(0);\n'
    i__fileHandler.write(s__anotate);
    s__main = "\n}\n";
    i__fileHandler.write(s__main);
    
    # Flush results to the file
    i__fileHandler.flush();
      
if(__name__ =="__main__"):
    l__file = open(C__FILENAME, 'wa');
    generate_includes(l__file);
    l__names = generate_functions(l__file);
    generate_test(l__file,l__names);
    l__file.close();
	
	
